L'évaluation paresseuse
(ou comment faire les choses plus tard peut être une bonne idée)
David Sferruzza
À propos de moi
- @d_sferruzza
- github.com/dsferruzza
- développeur et responsable R&D chez Escale
- doctorant en génie logiciel à l'Université de Nantes
- écrit des projets perso et pro en Scala et en Haskell (notamment) depuis ~ 2 an
Évaluation paresseuse !=
Learn the difference, it could save your life
Stratégie d'évaluation
- quand évaluer les arguments d'un appel de fonction
- quel type de valeur passer à la fonction
Évaluation stricte
strict evaluation, eager evaluation, greedy evaluation
- quand : dès que l'expression peut être liée à une variable
- quel type de valeurs :
- call by value
- call by reference
- call by sharing
- ...
Évaluation non stricte
non-strict evaluation, lazy evaluation
- call by name : les arguments sont substitués dans le corps de la fonction
- call by need : idem, avec mémoïsation (≈ mise en cache du résultat de l'évaluation des arguments)
- ...
Évaluation paresseuse
L'exécution d'un bout de code ne se fait pas avant que les résultats de ce bout de code ne soient réellement nécessaires.
À quoi ça sert ?
- optimisation : on peut éviter des calculs inutiles
- maintenabilité :
- on peut exprimer des structures de données infinies
- on peut définir des structures de contrôle comme des abstractions, au lieu de primitives
Lo-Dash
A JavaScript utility library delivering consistency, modularity, performance, & extras.
- bibliothèque JS qui permet (notamment) de manipuler les collections
- lazy depuis la v3
Exemple
var t = [0, 1, 2, 3, 4];
function plusUn(nb) {
console.log(nb + ' + 1');
if (nb > 2) console.log('Traitement long');
return nb + 1;
}
function petit(nb) {
console.log(nb + ' plus petit que 3 ?');
return nb < 3;
}
Sans Lo-Dash
var js = t
.map(plusUn)
.filter(petit)
.slice(0, 2);
0 + 1
1 + 1
2 + 1
3 + 1
Traitement long
4 + 1
Traitement long
1 plus petit que 3 ?
2 plus petit que 3 ?
3 plus petit que 3 ?
4 plus petit que 3 ?
5 plus petit que 3 ?
[ 1, 2 ]
Avec Lo-Dash
var _ = require('lodash');
var lodash = _(t)
.map(plusUn)
.filter(petit)
.take(2)
.value();
0 + 1
1 plus petit que 3 ?
1 + 1
2 plus petit que 3 ?
[ 1, 2 ]
Conclusion
Still not that kind of lazy
Conclusion
- séparation
- du Calcul, de la génération
→ où le calcul d'une valeur est-il défini ?
- du Contrôle, de la condition d'arrêt
→ où le calcul d'une valeur se produit-il ?
- colle qui permet d'assembler efficacement des (bouts de) programmes : facilite l'approche diviser pour régner
Avantages : peut augmenter la maintenabilité et les performances
Inconvénients : peut introduire de l'overhead (dépend pas mal de la techno)